using System;

using Number = System.Int32;

namespace DanielSig
{
	public static class XInt
	{
		public static Number Sign(this Number thisValue)
		{
			return thisValue < 0 ? -1 : 1;
		}
		public static bool SignBit(this Number thisValue)
		{
			return thisValue < 0;
		}
		public static Number NumBits(this Number thisValue)
		{
			thisValue &= Number.MaxValue;
			int val = 0;
			if(thisValue > (1 << 16))
			{
				val += 16;
				thisValue >>= 16;
			}
			if(thisValue > (1 << 8))
			{
				val += 8;
				thisValue >>= 8;
			}
			if(thisValue > (1 << 4))
			{
				val += 4;
				thisValue >>= 4;
			}
			if(thisValue > (1 << 2))
			{
				val += 2;
				thisValue >>= 2;
			}
			if(thisValue > 2)
			{
				val++;
				thisValue >>= 1;
			}
			if(thisValue > 0) val++;
			
			return val;
		}
		public static Number Clamp(this Number thisValue)
		{
			return thisValue.Clamp(1);
		}
		public static Number Clamp(this Number thisValue, Number limit)
		{
			if(thisValue > limit) return limit;
			if(thisValue < 0) return 0;
			return thisValue;
		}
		public static Number ClampBetween(this Number thisValue, Number min, Number max)
		{
			return thisValue.Max(min).Min(max);
		}
		public static Number Abs(this Number thisValue)
		{
			return thisValue > 0 ? thisValue : -thisValue;
		}

		public static Number Max(this Number thisValue, Number value)
		{
			return thisValue > value ? thisValue : value;
		}
		public static Number Min(this Number thisValue, Number value)
		{
			return thisValue < value ? thisValue : value;
		}
		public static Number GetDistance(this Number thisValue, Number value)
		{
			if(thisValue > value)
			{
				return thisValue - value;
			}
			return value - thisValue;
		}
		public static Number MoveTowards(this Number thisValue, Number value, Number maxDistanceDelta)
		{
			if(thisValue - maxDistanceDelta > value)
				return thisValue - maxDistanceDelta;
			if(thisValue + maxDistanceDelta < value)
				return thisValue + maxDistanceDelta;
			return value;
		}
		public static Number Lerp(this Number thisValue, Number value, double amount)
		{
			return (Number)(thisValue + (value - thisValue) * amount);
		}
		public static Number Half(this Number thisValue)
		{
			return (Number)(thisValue * 0.5F);
		}
		public static Number Double(this Number thisValue)
		{
			return thisValue * 2;
		}
		public static Number Repeat(this Number thisValue, Number limit)
		{
			return (thisValue % limit) + (thisValue < 0 ? limit : 0);
		}
		public static Number RepeatBetween(this Number thisValue, Number min, Number max)
		{
			return min < max ? ((thisValue - min).Repeat(max - min)) + min : min - ((thisValue - max).Repeat(min - max));
		}
		public static String ToBitString(this Number thisValue)
		{
			uint bitIndex = 0;
			byte[] data = new byte[4];
			data.WriteInt(thisValue, ref bitIndex, 32);
			return data.ToBitString();
		}
		public static String ToHexString(this Number thisValue)
		{
			uint bitIndex = 0;
			byte[] data = new byte[4];
			data.WriteInt(thisValue, ref bitIndex, 32);
			return data.ToHexString();
		}
		public static bool IsBetween(this Number thisValue, Number min, Number max)
		{
			return min < thisValue && thisValue < max;
		}
	}
}

